using System;
using Xunit;
using Tribe.Cache.Enum;

namespace Tribe.Cache.Test
{
    public class CacheTests 
    {
        private readonly Cache _cache;

        public CacheTests()
        {
            _cache = new Cache();
        }

        [Fact]
        public void AnItemShouldBeAbleToBeAddedToTheCacheThenRetrieved()
        {
            _cache.Clear();
            Phone phone = new Phone { PhoneName = "IPHONE" };
            _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(5));
            string phoneName = _cache.Get("__Phone", () =>"ANDRIOD", TimeSpan.FromSeconds(5));
            Assert.Equal("IPHONE", phoneName);
        }
        [Fact]
        public void AnItemShouldBeAbleToBeRemovedFromTheCacheThenAFreshItemShouldBeAbleToBeRetrieved()
        {
            _cache.Clear();

            Phone phone = new Phone { PhoneName = "IPHONE" };
            _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(5));
            phone.PhoneName = "BLACKBERRY";
            Assert.NotEqual("BLACKBERRY", _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(5)));
            _cache.Clear();
            string phoneName = _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(1));
            Assert.Equal("BLACKBERRY", phoneName);
        }
        [Fact]
        public void AnItemShouldBeAbleToBeAddedToTheCacheWithItsExpirationTypeSetToSliding()
        {
            _cache.Clear();
            Phone phone = new Phone { PhoneName = "IPHONE" };
            Assert.DoesNotThrow(() => _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(5), CacheExpiration.Sliding));
        }
        [Fact]
        public void AnItemShouldBeAbleToBeAddedToTheCacheWithItsExpirationTypeSetToSlidingReturningTheCorrectInstaceAfterMultipleRetrievals()
        {
            _cache.Clear();
            Phone phone = new Phone { PhoneName = "IPHONE" };
            
            string phoneName = _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(1), CacheExpiration.Sliding);
            Assert.Equal("IPHONE", phoneName);

            System.Threading.Thread.Sleep(new TimeSpan(0,0,0,0,600));
            phone.PhoneName = "BLACKBERRY";
            phoneName = _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(1), CacheExpiration.Sliding);
            Assert.Equal("IPHONE", phoneName);
            
            System.Threading.Thread.Sleep(new TimeSpan(0, 0, 0, 0, 600));
            phoneName = _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(1), CacheExpiration.Sliding);
            Assert.Equal("IPHONE", phoneName);
            
            System.Threading.Thread.Sleep(new TimeSpan(0, 0, 0, 2, 0));
            phoneName = _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(1), CacheExpiration.Sliding);
            Assert.Equal("BLACKBERRY", phoneName);
        }
        [Fact]
        public void AnItemShouldBeAbleToBeRemovedFromTheCache()
        {
            _cache.Clear();
            Phone phone = new Phone { PhoneName = "IPHONE" };
            _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(5));
            Assert.Equal(1, _cache.Count());
            _cache.Delete("__Phone");
            Assert.Equal(0, _cache.Count());

        }
        [Fact]
        public void WhenCallingClearAllTheCacheItemsShouldBeRemovedFromTheCache()
        {
            _cache.Clear();
            Assert.Equal(0, _cache.Count());
            Phone phone = new Phone { PhoneName = "IPHONE" };
            _cache.Get("__Phone", phone.ToString, TimeSpan.FromSeconds(5));
            Assert.Equal(1, _cache.Count());
            _cache.Clear();
            Assert.Equal(0, _cache.Count());
        }

        internal class Phone
        {
            public string PhoneName { get; set; }

            public override string ToString()
            {
                return PhoneName;
            }
        }
    }
}